/*
* Vector3.cpp
*
*  Created on: Jan 14, 2012
*  
*/

#include  "Vector3.h"
#include <math.h>

namespace Physics
{
#pragma region CONSTRUCTORs
	//C003: Copy Constructor
	Vector3::Vector3(const Vector3 &vec)
	{
		this->x = vec.getX();
		this->y = vec.getY();
		this->z = vec.getZ();
	}
#pragma endregion


#pragma region PROPERTIES
	//M001: Setter X-value
	void Vector3::setX(const float &x) { this->x = x; }

	//M002: Getter X-value
	float Vector3::getX() const { return this->x; }

	//M003: Setter Y-value
	void Vector3::setY(const float &y) { this->y = y; }

	//M004: Getter Y-value
	float Vector3::getY() const { return this->y; }

	//M005: Setter Z-value
	void Vector3::setZ(const float &z) {this->z = z; }

	//M006: Getter Z-value
	float Vector3::getZ() const { return this->z; }

	//M007: Setter XYZ-value
	void Vector3::setXYZ(const float &x, const float &y, const float &z)
	{
		this->x = x;  this->y = y;  this->z = z;
	}

	//M008: Setter XYZ-value
	void Vector3::setXYZ(const Vector3 &vec)
	{
		//*this = vec;
		this->x = vec.getX();  
		this->y = vec.getY();  
		this->z = vec.getZ();
	}

	//M009: Getter XYZ-value
	const Vector3& Vector3::getXYZ() const
	{
		return (*this);
	}
#pragma endregion


#pragma region OVERLOADED-OPERATORs
	//M010: 
	const Vector3 Vector3::operator+(const Vector3 &vec)
	{
		return Vector3( (this->x + vec.getX()), (this->y + vec.getY()), (this->z + vec.getZ()) );
	}

	//M011: 
	const Vector3 Vector3::operator-(const Vector3 &vec)
	{
		return Vector3( (this->x - vec.getX()), (this->y - vec.getY()), (this->z - vec.getZ()) );
	}

	//M012: 
	const Vector3 Vector3::operator*(const Vector3 &vec)
	{
		return Vector3( (this->x * vec.getX()), (this->y * vec.getY()), (this->z * vec.getZ()) );
	}

	//M013: Assignment Operator
	const Vector3& Vector3::operator=(const Vector3 &vec)
	{
		if ( this != &vec) //Check for NO self assignment
		{
			//Deallocate, allocate new space, copy values...
			this->x = vec.getX();
			this->y = vec.getY();
			this->z = vec.getZ();
		}
		
		return *this;
	}

	//M014: 
	bool Vector3::operator==(const Vector3 &vec)
	{
		return (this->x == vec.getX() && this->y == vec.getY() && this->z == vec.getZ());
	}
#pragma endregion


#pragma region HELPER-METHODS
	//M016: Helper Method, Return ZERO-value
	const Vector3 Vector3::zero() const
	{
		return Vector3();
	}
#pragma endregion

	float Vector3::findDistance(Vector3 const &vec)
	{
		// sqrt( ( vec.x - this.x )^2 + (vec.y - this.y )^2 + (vec.z - this.z )^2 )
		return sqrt( ( ( vec.getX() - this->x ) * (vec.getX() - this->x) ) + ( ( vec.getY() - this->y ) * (vec.getY() - this->y) ) +  ( ( vec.getY() - this->y ) * (vec.getZ() - this->z) ));
	}
	
	float Vector3::dotProduct(Vector3 const &vec)
	{
		float tempX, tempY, tempZ;

		tempX = this->x * vec.getX();
		tempY = this->y * vec.getY();
		tempZ = this->z * vec.getZ();

		return (tempX + tempY + tempZ);
	}

	float Vector3::magnitude()
	{
		return sqrt( (this->x * this->x) + (this->y * this->y) + (this->z * this->z) );
	}

	void Vector3::normalize()
	{
		this->x = (this->x / magnitude() );
		this->y = (this->y / magnitude() );
		this->z = (this->z / magnitude() );
	}

	Vector3 Vector3::crossProduct(Vector3 const &vec)
	{
		float x, y, z;

		x = (this->y * vec.getZ()) - ( this->z * vec.getY());
		y = (-1) * ((this->x * vec.getZ()) - (this->z * vec.getX()));
		z = (this->x * vec.getY()) - (this->y * vec.getX());

		return Vector3(x, y, z);
	}
} /* NAMESPACE */